package zzps.exeed.kernel.tool;

import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.stream.Collectors;

public class AnnotationTool {


    private final static Class[] metaAnnotations = {Documented.class, Inherited.class, Native.class, Repeatable.class, Retention.class, Target.class};


    /**
     * 递归查找是否含有某注解
     */
    public static <A extends Annotation> A getAnnotationRecursion(Class<?> target,Class<A> annotationClass){
        A findAnnotation;
        findAnnotation = target.getAnnotation(annotationClass);
        if (findAnnotation != null){
            return findAnnotation;
        }
        Annotation[] annotations = target.getAnnotations();
        List<Annotation> list = Arrays.stream(annotations).filter(a1 -> Arrays.stream(metaAnnotations).noneMatch(a2 -> a1.annotationType() == a2)).collect(Collectors.toList());
        for (Annotation a : list) {
            findAnnotation = getAnnotationRecursion(a.annotationType(), annotationClass);
            if (findAnnotation != null){
                return findAnnotation;
            }
        }
        return null;
    }

    /**
     * 返回直接类class上过滤了元注解的数组
     */
    public static Annotation[]  getAnnotations(Class<?> target){
        Annotation[] annotations = target.getAnnotations();
        Annotation[] array = Arrays.stream(annotations).filter(a1 -> Arrays.stream(metaAnnotations).noneMatch(a2 -> a1.annotationType() == a2)).toArray(Annotation[]::new);
        return array;
    }
    /**
     * 返回直接方法上过滤了元注解的数组
     */
    public static Annotation[]  getAnnotations(Method method){
        Annotation[] annotations = method.getAnnotations();
        Annotation[] array = Arrays.stream(annotations).filter(a1 -> Arrays.stream(metaAnnotations).noneMatch(a2 -> a1.annotationType() == a2)).toArray(Annotation[]::new);
        return array;
    }

    /**
     * 返回直接参数上过滤了元注解的数组
     */
    public static Annotation[] getAnnotations(Parameter parameter){
        Annotation[] annotations = parameter.getDeclaredAnnotations();
        Annotation[] array = Arrays.stream(annotations).filter(a1 -> Arrays.stream(metaAnnotations).noneMatch(a2 -> a1.annotationType() == a2)).toArray(Annotation[]::new);
        return array;
    }

}
